import json
from typing import List
import re
def is_json(invoke):
    try:
        json.loads(invoke)
    except ValueError:
        return False
    return True

def check_action_invoke_structure(action: str):
    valid = 1
    think_pattern = r"</think>"
    think_match = re.search(think_pattern, action, re.DOTALL)
    if not think_match:
        valid = 0
        return valid
    # 添加边界检查
    think_end_pos = think_match.end()
    if think_end_pos >= len(action):
        # 如果 </think> 在字符串末尾，after_think 应该是空字符串
        after_think = ""
    else:
        after_think = action[think_end_pos:]

    if "<action>" in after_think:
        action_count = after_think.count("<action>")
        invoke_count = after_think.count("<invoke>")
        #如果think后出现<action>，如果没出现</action>，<action>词条数不为1，invoke词条数目不为1，action不以</invoke>结尾，那么valid=0
        if "</action>" not in after_think and action_count != 1 and invoke_count != 1 and not action.strip().endswith("</invoke>"):
            valid = 0
    return valid


def mirrorapi_projection(actions: List[str]):
    """
    A function to process the actions.
    actions: the list of actions to be processed, it is a list of strings.
    Expected format:
        <think>some reasoning...</think><action>up/down/left/right/still</action>
    """
    # print(f"### action 0 {actions[0]}")
    valids = []
    actions_results = []
    invoke_results = []
    memory_results = []

    
    for action in actions:
        valid = 1
        match_action = re.search(r"<action>(.*?)</action>", action, re.DOTALL)
        match_invoke = re.search(r"<invoke>(.*?)</invoke>", action, re.DOTALL)
        match_answer = re.search(r"<answer>(.*?)</answer>", action, re.DOTALL)
        # match_memory = re.search(r"<memory>(.*?)</memory>", action, re.DOTALL)
        match_invoke_res = match_invoke.group(1).strip() if match_invoke else None
        valid = check_action_invoke_structure(action)
        if match_answer:
            invoke_results.append("Answer")
            actions_results.append(match_answer.group(1).strip())
            valids.append(valid)
            continue

        if match_action:
            actions_results.append(match_action.group(1).strip())
        else:
            actions_results.append("error")
            valid = 0
        if match_invoke and is_json(match_invoke_res):
            invoke_results.append(match_invoke_res)
        else:
            invoke_results.append(None)
            valid = 0
        # if match_memory:
        #     memory_results.append(match_memory.group(1).strip())
        # else:
        #     memory_results.append("error")
        #     valid = 0
        valids.append(valid)
    assert len(actions_results) == len(invoke_results)
    assert len(actions_results) == len(valids)
    return actions_results, invoke_results, memory_results, valids